package com.vesystem.vegua.websocket;

import com.vesystem.vegua.config.GlobalConfig;
import com.vesystem.vegua.modules.common.dto.TunnelDto;
import com.vesystem.vegua.modules.common.entity.RemoteApp;
import com.vesystem.vegua.modules.common.service.impl.RemoteAppServiceImpl;
import com.vesystem.vegua.utils.TunnelTools;
import org.apache.guacamole.GuacamoleException;
import org.apache.guacamole.net.GuacamoleTunnel;
import org.apache.guacamole.net.InetGuacamoleSocket;
import org.apache.guacamole.net.SimpleGuacamoleTunnel;
import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket;
import org.apache.guacamole.protocol.GuacamoleClientInformation;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.websocket.EndpointConfig;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @auther hcy
 * @create 2020-12-08 14:26
 * @Description
 */
@Component
@ServerEndpoint(value = "/gua",subprotocols = "guacamole")
public class WebSocketTunnel extends GuacamoleWebSocketTunnelEndpoint {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 解决websocket中不能直接注入spring单例对象的问题
     */
    private static RemoteAppServiceImpl remoteAppService;
    @Autowired
    public void setRemoteAppServiceImpl(RemoteAppServiceImpl remoteAppService){
        WebSocketTunnel.remoteAppService = remoteAppService;
    }

    /**
     * 保存tunnel连接，key为登录名，第三方接入系统请自行保证登录名不重复
     */
    public static Map<String,TunnelDto> guacamoleTunnelMap = new ConcurrentHashMap<>();

    @Override
    protected GuacamoleTunnel createTunnel(Session session, EndpointConfig endpointConfig){
        log.info( session.getRequestURI().toString() );
        Map<String, List<String>> parameterMap =  session.getRequestParameterMap();
        String sourceType = parameterMap.get("sourceType").get(0);
        GuacamoleConfiguration config;
        TunnelDto tunnelDto = new TunnelDto();
        String loginname = "";
        if (Objects.equals(sourceType,"1")){
            String windowsWidth = parameterMap.get("width").get(0);
            String windowsHeight = parameterMap.get("height").get(0);
            Integer appId = Integer.valueOf(parameterMap.get("connectionParam").get(0));
            RemoteApp dbApp = remoteAppService.getRemoteAppInfoById(appId);
            config = TunnelTools.createGuaConfigAboutGua(windowsWidth,windowsHeight,dbApp);
            tunnelDto.setProtocol( dbApp.getProtocol() );
            loginname = "1_"+parameterMap.get("loginname").get(0);
        }else {
            config = TunnelTools.createGuaConfigAboutUam( parameterMap );
            tunnelDto.setProtocol( 1 );
            loginname = "2_"+parameterMap.get("loginname").get(0);
        }
        //todo 需要测试gua对象中传过来的参数在什么地方在调整
        GuacamoleClientInformation clientInformation = TunnelTools.createClientConfig("");
        if ( config != null ){
            try {
                ConfiguredGuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                        new InetGuacamoleSocket(GlobalConfig.PROXY_IP,GlobalConfig.PROXY_PORT),config,clientInformation );
                GuacamoleTunnel tunnel = new SimpleGuacamoleTunnel(socket);
                System.out.println( tunnel.getUUID() );
                tunnelDto.setGuacamoleTunnel(tunnel);
                tunnelDto.setRemoteApp( config.getParameter("remote-app") );
                tunnelDto.setServerIp( config.getParameter("hostname") );
                tunnelDto.setServerPort( Integer.parseInt(config.getParameter("port")) );

                guacamoleTunnelMap.put(loginname,tunnelDto);
                return tunnel;
            } catch (GuacamoleException e) {
                log.error(e.getLocalizedMessage(),e);
            }
        }
        return null;
    }
}
